package com.feidee.data.report.dao.impl;

import com.feidee.data.report.constant.Constant;
import com.feidee.data.report.dao.IReportMetadataOpr;
import com.feidee.data.report.dao.IReportAndSourceStatusDao;
import com.feidee.data.report.exception.DataDaoException;
import com.feidee.data.report.model.DataResourcesModel;
import com.feidee.data.report.model.ReportConfiguration;
import com.feidee.data.report.model.ReportLogModel;
import com.feidee.data.report.model.ReportParam;
import com.feidee.data.report.util.DbOperationUtil;
import com.feidee.data.report.util.JdbcManager;
import com.feidee.data.report.util.ReportMetadataComparator;
import com.feidee.data.report.util.TimeUtil;
import com.feidee.data.report.util.ToolUtils;
import com.feidee.fdcommon.configuration.CustomConfiguration;
import com.feidee.fdhadoop.logCollect.LogCollectService;
import org.apache.log4j.Logger;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.PriorityBlockingQueue;

public class ReportMetadataOprImpl implements IReportMetadataOpr {

    private static Logger logger = Logger.getLogger(ReportMetadataOprImpl.class);

    private DataSource confDataSource;
    private IReportAndSourceStatusDao reportAndSourceStatusDao;

    /**
     * 获取需要执行的hql和sql
     */
    public synchronized int getHqlSql(ReportParam rp,
                                      PriorityBlockingQueue<ArrayList<ReportConfiguration>> hqlSqlQueue) {
        // 连接数据库执行SQL
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        String curKey = null; // 存储当前处理的

        try {
            String kpi = rp.getKpi();
            String index = rp.getIndex();
            String backup = rp.getBackup();
            String isCRFlag = rp.getIsCustom();
            String enable = rp.getEnable();
            String period = rp.getPeriod();
            conn = confDataSource.getConnection();
            logger.info("正常获取配置库连接 conn:" + conn);
            statement = conn.createStatement();
            // 每天需要固定运行一次的更新频率
            List<String> everydayFrequeuecy = Arrays
                    .asList(CustomConfiguration.getString("everyday.run.frequenecy", "7").split(Constant.FREQUENCY_SPLIT_FLAG));

            /* 组装SQL */
            StringBuffer sqlBuf = new StringBuffer();
            if ("2".equals(rp.getIsSchedule()) && rp.getDataResources() != null) {
                // 根据数据源重跑报表并精确重跑依赖失败的报表
                String dataResources = rp.getDataResources();
                String dataResourcesSql = "SELECT a.* FROM (\n" +
                        "\tSELECT * FROM report_sql WHERE is_enable = 1 AND \n" +
                        "\t(data_resources LIKE '%," + dataResources + "' OR data_resources LIKE '" + dataResources + ",%' " +
                        "OR data_resources LIKE '%," + dataResources + ",%' OR data_resources='" + dataResources + "')\n" +
                        ") a\n" +
                        "INNER JOIN (\n" +
                        "\tSELECT * FROM report_exec_status WHERE exec_status IN ('DRSB','DRCS','DDCS')\n" +
                        ") b\n" +
                        "ON a.report_key = b.report_key\n";
                String dependencySql = getDependencySql(dataResourcesSql, statement);
                sqlBuf.append(dataResourcesSql);
                if (ToolUtils.isNotNull(dependencySql)) {
                    sqlBuf.append("UNION ALL\n" + dependencySql + "\n");
                }
            } else if ("3".equals(rp.getIsSchedule()) && rp.getDataResources() != null) {
                // 手动按数据源执行报表
                String[] dataResourcesArray = rp.getDataResources().split(",");
                sqlBuf.append("SELECT * FROM report_sql WHERE is_enable = 1 AND (");
                for (int i = 0; i < dataResourcesArray.length; i++) {
                    if (i != 0) {
                        sqlBuf.append(" OR ");
                    }
                    sqlBuf.append("data_resources LIKE '%," + dataResourcesArray[i] + "' OR data_resources LIKE " +
                            "'" + dataResourcesArray[i] + ",%' " +
                            "OR data_resources LIKE '%," + dataResourcesArray[i] + ",%' OR data_resources='" + dataResourcesArray[i] + "'");
                }
                sqlBuf.append(")");
            } else {

                sqlBuf.append("SELECT * FROM report_sql WHERE ");
                // 如果是自定义报表,则不再判断是否启用
                // 如果指定了enable值，则调起配置库中is_enable为指定值的报表
                // 如果未指定enable值，则默认调起is_enable字段为1的报表
                if ("1".equals(isCRFlag)) {
                    sqlBuf.append("is_custom = 1 ");
                } else if (ToolUtils.isNotNull(enable)) {
                    sqlBuf.append("is_enable = " + enable + " ");
                } else {
                    sqlBuf.append("is_enable = 1 ");
                }

                if (ToolUtils.isNotNull(kpi) && !kpi.equals("all")) {
                    sqlBuf.append("AND report_key = '" + kpi + "' ");
                }
                if (ToolUtils.isNotNull(index) && !kpi.equals("all")) {
                    if (index.contains(",")) {
                        String[] splitIndex = index.split(",", -1);
                        String tempIndex = "";
                        for (String temp : splitIndex) {
                            tempIndex += temp + ",";
                        }
                        tempIndex = tempIndex.substring(0, tempIndex.length() - 1);
                        sqlBuf.append("AND report_index in (" + tempIndex + ") ");
                    } else {
                        sqlBuf.append("AND report_index = " + index + " ");
                    }
                }
                if (ToolUtils.isNotNull(period)){
                    sqlBuf.append("AND run_date = ").append(period).append(" ");
                }
            }
            sqlBuf.append("ORDER BY priority desc, report_key desc, report_index asc");
            String mysqlString = sqlBuf.toString();

            logger.info("#### Ready to get HQL " + mysqlString);
            // 是否执行历史sql
            String historyFlag = rp.getHistory();
            String historySqlFlag = "";
            if ("1".equals(historyFlag)) {
                historySqlFlag = "hqlhistory";
            } else {
                historySqlFlag = "hqlcontext";
            }

            /* 如果传入backup字段，则进行数据库备份 */
//            if ("1".equals(backup)) {
//                backUpReportSql();
//            }

            /* 筛选hqlsql */
            rs = statement.executeQuery(mysqlString);
            ArrayList<ReportConfiguration> list = new ArrayList<ReportConfiguration>();
            int runPriority = 1; //运行优先级，方便后续优先级队列进行调度
            while (rs.next()) {
                String reportKey = rs.getString("report_key");
                String reportIndex = rs.getString("report_index");
                String sqlContext = rs.getString("sqlcontext");
                String hqlContext = rs.getString(historySqlFlag);
                String runDate = rs.getString("run_date");
                String operation = rs.getString("operation");
                String engine = rs.getString("engine");
                String process_class = rs.getString("process_class");
                String table_type = rs.getString("table_type");
                String mysql_table = rs.getString("mysql_table");
                String mysql_keys = rs.getString("mysql_keys");
                String isCustom = rs.getString("is_custom");
                String reportDependency = rs.getString("report_dependency");
                String isScheduler = rs.getString("is_schedule");
                String dataResources = rs.getString("data_resources");
                int tablePriority = rs.getInt("priority");
                // 此处只有前端提交报表或者发布报表或者手动触发enable为0的报表rp的enable值才会设置为0
                String is_enable = rp.getEnable();

                /* 检查数据内容的合法性 */
                if (!ToolUtils.isNotNull(reportKey) || !ToolUtils.isNotNull(reportIndex)
                        || !ToolUtils.isNotNull(runDate)) {
                    logger.info("Mysql Data Exception.....");
                    continue;
                }

                /* 判断今天是否应该执行, 不在每天需要执行的更新频率内并且不是自定义报表*/
                if ((!everydayFrequeuecy.contains(runDate)) && (!"1".equals(isCRFlag))) {
                    String weekOfData = TimeUtil.getWeekOfDate();
                    if (!runDate.contains(weekOfData)) {
                        logger.info("This Report_key: " + reportKey + "_" + reportIndex
                                + " won't be executed today! It should be execute within " + runDate);
                        continue;
                    }
                }

                if (!ToolUtils.isNotRealNull(hqlContext)) {
                    hqlContext = "";
                }
                ReportConfiguration reportconfiguration = new ReportConfiguration(reportKey, reportIndex, hqlContext,
                        sqlContext, runDate, operation, engine, process_class);
                reportconfiguration.setTable_type(table_type);
                reportconfiguration.setMysql_table(mysql_table);
                reportconfiguration.setMysql_keys(mysql_keys);
                reportconfiguration.setIsCustom(isCustom);
                reportconfiguration.setReportDependency(reportDependency);
                reportconfiguration.setEnqueueTime(System.currentTimeMillis());
                reportconfiguration.setRunHistory(historyFlag);
                reportconfiguration.setTablePriority(tablePriority);
                reportconfiguration.setIsEnable(is_enable);
                reportconfiguration.setIsScheduler(isScheduler);
                reportconfiguration.setDataResources(dataResources);

                /* 根据curKey和listIndex参数的值，决定将当前 hql-sql 放置到哪个list中 */
                if (!ToolUtils.isNotNull(curKey)) {
                    curKey = reportKey; // 第一次添加
                } else if (ToolUtils.isNotNull(curKey) && !reportKey.equals(curKey)) {
                    /* 首先将历史的hqlSqlStr存储到队列中，并重新记录 */
                    boolean pushQueueRes = hqlSqlQueue.offer(list);
                    if (!pushQueueRes) {
                        logger.info("报表 " + curKey + " 入队失败...");
                    } else {
                        runPriority += 1;
                        logger.info("报表 " + curKey + " 将执行...");
                        // 更改报表执行状态为等待执行
                        reportAndSourceStatusDao.changeReportRunStatus(curKey,
                                Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE);
                        reportAndSourceStatusDao.updateReportRunTime(curKey,
                                Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE,
                                ToolUtils.getPriorityLevel(list.get(0).getTablePriority()),
                                System.currentTimeMillis(), "");
                    }
                    list = new ArrayList<ReportConfiguration>();
                    curKey = reportKey;
                }

                //设置运行优先级
                reportconfiguration.setRunPriority(runPriority);

                list.add(reportconfiguration);
            }
            if (list.size() != 0) {
                boolean pushQueueRes = hqlSqlQueue.offer(list);
                if (!pushQueueRes) {
                    logger.info("报表 " + curKey + " 入队失败...");
                } else {
                    logger.info("报表 " + curKey + " 将执行...");
                    // 更改报表执行状态为等待执行
                    reportAndSourceStatusDao.changeReportRunStatus(curKey, Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE);
                    reportAndSourceStatusDao.updateReportRunTime(curKey, Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE,
                            ToolUtils.getPriorityLevel(list.get(0).getTablePriority()), System.currentTimeMillis(), "");
                }
            }

        } catch (SQLException e) {
            logger.info("#### Execute MysqlString failed..... ####");
            return -1;
        } finally {
            DbOperationUtil.cleanConnEnv(conn, statement, rs);
        }

        return 0;
    }

    /**
     * 获取待运行的报表依赖失败
     *
     * @param dataResourcesSql
     * @param statement
     * @return
     */
    private String getDependencySql(String dataResourcesSql, Statement statement) {
        String dependencySql = "";
        ResultSet resultSet = null;
        try {
            boolean hasResult = false;
            StringBuilder dependencySqlBuilder = new StringBuilder("SELECT a.* FROM (\n" +
                    "\tSELECT * FROM report_sql WHERE is_enable = 1 AND \n\t");
            List<String> runReportKey = new ArrayList<>();
            resultSet = statement.executeQuery(dataResourcesSql);
            while (resultSet.next()) {
                String reportKey = resultSet.getString("report_key");
                if (!runReportKey.contains(reportKey)) {
                    dependencySqlBuilder.append("(report_dependency RLIKE '.*," + reportKey + "$' OR " +
                            "report_dependency RLIKE '^" + reportKey + ",.*' " +
                            "OR report_dependency RLIKE '.*," + reportKey + ",.*' OR report_dependency='" + reportKey + "')\n\tOR ");
                    runReportKey.add(reportKey);
                }
                hasResult = true;
            }
            if (!hasResult) {
                return dependencySql;
            }
            dependencySqlBuilder.append(") a\n" +
                    "INNER JOIN (\n" +
                    "    SELECT * FROM report_exec_status WHERE exec_status IN ('ZXSB','DRCS','DDCS')\n" +
                    ") b\n" +
                    "ON a.report_key = b.report_key");
            dependencySql = dependencySqlBuilder.toString().replace("\n\tOR )", ")");
        } catch (Exception e) {
            logger.error("获取依赖待运行报表的报表SQL失败", e);
        } finally {
            DbOperationUtil.cleanConnEnv(resultSet);
        }
        return dependencySql;
    }

    /**
     * 执行数据库备份
     */
    public void backUpReportSql() {

        Calendar cal = Calendar.getInstance();
        String dateStr = TimeUtil.parseDate2Str(cal, "yyyy_MM_dd");
        cal.add(Calendar.DATE, -1);
        String yesStr = TimeUtil.parseDate2Str(cal, "yyyy_MM_dd");
        StringBuffer mysqlStr = new StringBuffer();
        Connection conn = null;
        Statement st = null;
        ResultSet tabs = null;
        try {
            conn = confDataSource.getConnection();
            st = conn.createStatement();
            /* 备份数据库 */
            mysqlStr.append("create table report_sql_" + dateStr + " like report_sql");
            st.executeUpdate(mysqlStr.toString());
            mysqlStr.setLength(0);
            mysqlStr.append("insert into report_sql_" + dateStr + " select * from report_sql");
            st.executeUpdate(mysqlStr.toString());
            mysqlStr.setLength(0);
            /* 删除以前备份的数据库 */
            DatabaseMetaData dbMetaData = conn.getMetaData();
            String[] types = {"TABLE"};
            tabs = dbMetaData.getTables(null, null, null, types);
            String tableName = null;
            while (tabs.next()) {
                tableName = (String) tabs.getObject("TABLE_NAME");
                /* 保存近两天的表备份 */
                if (tableName.startsWith("report_sql") && !"report_sql".equals(tableName)
                        && !("report_sql_" + dateStr).equals(tableName)
                        && !("report_sql_" + yesStr).equals(tableName)) {
                    mysqlStr.append("drop table " + tableName);
                    st.executeUpdate(mysqlStr.toString());
                    mysqlStr.setLength(0);
                }
            }
        } catch (SQLException e) {
            ReportLogModel logs = new ReportLogModel();
            logs.setReport_key("backUpReportSql");
            logs.setReport_index("0");
            logs.setStatus(Constant.LOG_EXCEPTION);
            logs.setTs(TimeUtil.getNow(Constant.LOG_TIME_FORMAT));
            logs.setMsg("Backup Mysql Database Failed! msg:" + e.getMessage());
            LogCollectService.sendLog("bigdata", "data_report", logs);
            logger.error("#### Backup Mysql Database Failed! #### MSG:" + e.getMessage());
        } finally {
            DbOperationUtil.cleanConnEnv(conn, st, tabs);
        }
    }

    @Override
    public String updateDataResources(DataResourcesModel dataResourcesModel) {
        Connection conn = null;
        PreparedStatement st = null;
        try {
            if (!dataResourcesModel.getStatusTime().substring(0, 10).equals(ToolUtils.getCurrentDay())) {
                logger.info("#### 数据源表: " + dataResourcesModel.getMetaKey() + " 更新时间: " + dataResourcesModel.getStatusTime() + " 不是今天！");
                return "2";
            }
            conn = confDataSource.getConnection();
            String updateDataResourcesSql = "INSERT INTO  `report_metadata_status`(`meta_key`,`meta_status`,`msg`," +
                    "`status_time`) VALUES(?,?,?,?) " +
                    "ON DUPLICATE KEY UPDATE `meta_key`=?,`meta_status`=?,`msg`=?,`status_time`=?";
            st = conn.prepareStatement(updateDataResourcesSql);
            st.setString(1, dataResourcesModel.getMetaKey().toLowerCase());
            st.setString(2, dataResourcesModel.getMetaStatus());
            st.setString(3, dataResourcesModel.getMsg());
            st.setString(4, dataResourcesModel.getStatusTime());
            st.setString(5, dataResourcesModel.getMetaKey().toLowerCase());
            st.setString(6, dataResourcesModel.getMetaStatus());
            st.setString(7, dataResourcesModel.getMsg());
            st.setString(8, dataResourcesModel.getStatusTime());
            st.execute();
            logger.info("#### 数据源表: " + dataResourcesModel.getMetaKey() + " 更新同步状态成功!");
            return "0";
        } catch (Exception e) {
            logger.error("#### 数据源表: " + dataResourcesModel.getMetaKey() + " 更新同步状态失败: ", e);
            return "1";
        } finally {
            DbOperationUtil.cleanConnEnv(conn, st);
        }
    }

    /**
     * 获取指定更新频率需要执行的hql和sql,封装为队列方式返回
     *
     * @param frequency
     * @return
     */
    public PriorityBlockingQueue<ArrayList<ReportConfiguration>> getFrequencyHqlSqlList(String frequency) {

        PriorityBlockingQueue<ArrayList<ReportConfiguration>> hqlSqlQueue =
                new PriorityBlockingQueue<ArrayList<ReportConfiguration>>(
                CustomConfiguration.getInt("frequency.queue.size", 500), new ReportMetadataComparator());
        String mysqlDriver = CustomConfiguration.getString("mysql.jdbc.driverClassName");
        String mysqlUrl = CustomConfiguration.getString("mysql.jdbc.url");
        String mysqlUsername = CustomConfiguration.getString("mysql.jdbc.username");
        String mysqlPasswd = CustomConfiguration.getString("mysql.jdbc.password");

        /* 组装SQL */
        StringBuffer sqlBuf = new StringBuffer("SELECT * FROM report_sql WHERE");
        if (frequency.equals("W07")) {
            sqlBuf.append(" is_enable = 2 ");
        } else {
            sqlBuf.append(" is_enable = 1 ");
            sqlBuf.append("AND run_date = '").append(frequency).append("' ");
        }
        sqlBuf.append("ORDER BY priority desc, report_key desc, report_index asc");
        String mysqlString = sqlBuf.toString();

        logger.info("报表定时[ " + frequency + " ]执行, Ready to get HQL " + mysqlString);
        // 连接数据库执行SQL
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        String curKey = null; // 存储当前处理的

        try {
            conn = JdbcManager.getConnection(mysqlDriver, mysqlUrl, mysqlUsername, mysqlPasswd);
            statement = conn.createStatement();
            // 判断当前该服务器是否为活跃服务器，若非活跃服务器，则放弃本次定时任务执行
            if (!isCurrentHost(statement)) {
                logger.info("当前机器为非活跃机器，不执行SQL！");
                return hqlSqlQueue;
            }
            /* 筛选hqlsql */
            rs = statement.executeQuery(mysqlString);
            ArrayList<ReportConfiguration> list = new ArrayList<ReportConfiguration>();
            int runPriority = 1;  //运行优先级，方便后续优先级队列进行调度
            while (rs.next()) {
                String reportKey = rs.getString("report_key");
                String reportIndex = rs.getString("report_index");
                String sqlContext = rs.getString("sqlcontext");
                String hqlContext = rs.getString("hqlcontext");
                String runDate = rs.getString("run_date");
                String operation = rs.getString("operation");
                String engine = rs.getString("engine");
                String process_class = rs.getString("process_class");
                String table_type = rs.getString("table_type");
                String mysql_table = rs.getString("mysql_table");
                String mysql_keys = rs.getString("mysql_keys");
                String isCustom = rs.getString("is_custom");
                String reportDependency = rs.getString("report_dependency");
                String is_enable = rs.getString("is_enable");

                /* 检查数据内容的合法性 */
                if (!ToolUtils.isNotNull(reportKey) || !ToolUtils.isNotNull(reportIndex)
                        || !ToolUtils.isNotNull(runDate)) {
                    logger.info("报表定时执行, Mysql Data Exception.....");
                    continue;
                }

                if (!ToolUtils.isNotRealNull(hqlContext)) {
                    hqlContext = "";
                }
                ReportConfiguration reportconfiguration = new ReportConfiguration(reportKey, reportIndex, hqlContext,
                        sqlContext, runDate, operation, engine, process_class);
                reportconfiguration.setTable_type(table_type);
                reportconfiguration.setMysql_table(mysql_table);
                reportconfiguration.setMysql_keys(mysql_keys);
                reportconfiguration.setIsCustom(isCustom);
                reportconfiguration.setReportDependency(reportDependency);
                reportconfiguration.setEnqueueTime(System.currentTimeMillis());
                reportconfiguration.setRunHistory("0");
                reportconfiguration.setIsEnable("is_enable");


                /* 根据curKey和listIndex参数的值，决定将当前 hql-sql 放置到哪个list中 */
                if (!ToolUtils.isNotNull(curKey)) {
                    curKey = reportKey; // 第一次添加
                } else if (ToolUtils.isNotNull(curKey) && !reportKey.equals(curKey)) {
                    /* 首先将历史的hqlSqlStr存储到队列中，并重新记录 */
                    boolean pushQueueRes = hqlSqlQueue.offer(list);
                    if (!pushQueueRes) {
                        logger.info("报表定时执行, 报表 " + curKey + " 入队失败...");
                    } else {
                        runPriority += 1;
                        logger.info("报表定时执行, 报表 " + curKey + " 将执行...");
                        // 更改报表执行状态为等待执行
                        reportAndSourceStatusDao.changeReportRunStatus(curKey,
                                Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE);
                        reportAndSourceStatusDao.updateReportRunTime(curKey,
                                Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE,
                                "", System.currentTimeMillis(), "");
                    }
                    list = new ArrayList<ReportConfiguration>();
                    curKey = reportKey;
                }

                //设置运行优先级
                reportconfiguration.setRunPriority(runPriority);

                list.add(reportconfiguration);
            }

            if (list.size() != 0) {
                boolean pushQueueRes = hqlSqlQueue.offer(list);
                if (!pushQueueRes) {
                    logger.info("报表定时执行, 报表 " + curKey + " 入队失败...");
                } else {
                    logger.info("报表定时执行, 报表 " + curKey + " 将执行...");
                    // 更改报表执行状态为等待执行
                    reportAndSourceStatusDao.changeReportRunStatus(curKey, Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE);
                    reportAndSourceStatusDao.updateReportRunTime(curKey, Constant.REPORT_DEPENDENCY_WAITTING_EXECUTE,
                            "", System.currentTimeMillis(), "");
                }
            }
        } catch (DataDaoException e) {
            logger.info("报表定时执行, Connect to MySQL server failed..... ####");
            return null;
        } catch (SQLException e) {
            logger.info("报表定时执行, Execute MysqlString failed..... ####");
            return null;
        } finally {
            DbOperationUtil.cleanConnEnv(conn, statement, rs);
        }

        return hqlSqlQueue;
    }

    private boolean isCurrentHost(Statement statement) {
        String getIpSql = "select exec_status from report_exec_status " +
                "where report_key = '" + Constant.CURRENT_ALIVE_HOST_IP_KEY + "'";
        try {
            ResultSet resultSet = statement.executeQuery(getIpSql);
            if (resultSet.next()) {
                String ip = resultSet.getString("exec_status");
                if (ToolUtils.isNotNull(ip) && ip.equals(ToolUtils.getHostAddress())) {
                    logger.info("当前IP:" + Constant.CURRENT_ALIVE_HOST_IP_KEY + " 与记录IP：" + ip + " 相同！");
                    return true;
                }
                logger.info("当前IP:" + Constant.CURRENT_ALIVE_HOST_IP_KEY + " 与记录IP：" + ip + " 不相同！");
                return false;
            }
        } catch (Exception e) {
            logger.info("获取当前活跃IP异常，默认返回当前机器为活跃机器！", e);
        }
        return true;
    }

    public DataSource getConfDataSource() {
        return confDataSource;
    }

    public void setConfDataSource(DataSource confDataSource) {
        this.confDataSource = confDataSource;
    }

    public IReportAndSourceStatusDao getReportAndSourceStatusDao() {
        return reportAndSourceStatusDao;
    }

    public void setReportAndSourceStatusDao(IReportAndSourceStatusDao reportAndSourceStatusDao) {
        this.reportAndSourceStatusDao = reportAndSourceStatusDao;
    }

}
